package Day_0201.JUC;

/**
 * @author zxc
 * @date 2023/02/01 16:36
 **/
public class Synchronized {
    public static void main(String[] args) {
        /**
         * 谈一谈对于Synchronized关键字的理解
         * ===》
         * 1.synchronized关键字解决的是多个线程之间访问资源的同步性，
         *
         * 2.synchronized关键字可以保证被它修饰的方法或者代码块在任意时刻只能有一个线程执行。
         *
         * 另外，在 Java 早期版本中，synchronized属于重量级锁，效率低下，
         * 因为监视器锁（monitor）是依赖于底层的操作系统的Mutex Lock 来实现的，Java 的线程是映射到操作系统的原生线程之上的。
         * 如果要挂起或者唤醒一个线程，都需要操作系统帮忙完成，
         * 而操作系统实现线程之间的切换时需要从用户态转换到内核态，这个状态之间的转换需要相对比较长的时间，时间成本相对较高，这也是为什么早期的synchronized 效率低的原因。
         * 庆幸的是在 Java 6 之后 Java 官方对从 JVM 层面对synchronized 较大优化，所以现在的 synchronized 锁效率也优化得很不错了。
         *
         * 3.JDK1.6对锁的实现引入了大量的优化，如自旋锁、适应性自旋锁、锁消除、锁粗化、偏向锁、轻量级锁等技术来减少锁操作的开销。
         */

        /**
         * Synchronized关键字的使用
         * 1.修饰实例方法:
         * 作用于当前对象实例加锁，进入同步代码前要获得当前对象实例的锁;
         *  ===> 即，由于实例方法与实例对象密切相关，所以在调用实例方法前（Synchronized），需要获取该实例对象的对象锁;
         *
         * 2.修饰静态方法:
         * 也就是给当前类加锁，会作用于类的所有对象实例;
         * 因为静态成员不属于任何一个实例对象，是类成员（ static 表明这是该类的一个静态资源，不管new了多少个对象，只有一份）;
         * ===> 即，由于静态方法是属于当前类的，所以调用静态方法（Synchronized）前，需要获取该类的锁;
         *
         * 案例 ：
         * （1）所以如果一个线程A调用一个实例对象的非静态 synchronized 方法，
         * （2）而线程B需要调用这个实例对象所属类的静态 synchronized 方法，是允许的，不会发生互斥现象，
         *  ===》 因为访问静态 synchronized 方法占用的锁是当前类的锁，而访问非静态 synchronized 方法占用的锁是当前实例对象锁。
         *
         * 3.修饰代码块:
         * 指定加锁对象，对给定对象加锁，进入同步代码库前要获得给定对象的锁。
         *
         * 总结：
         * （1）synchronized 关键字加到 static 静态方法和 synchronized(class)代码块上都是是给 Class 类上锁。
         * （2）synchronized关键字加到实例方法上是给对象实例上锁。
         * 注意 ：尽量不要使用 synchronized(String a) 因为JVM中，字符串常量池具有缓存功能！
         */

        /**
         * Vector类是否为线程安全的？
         * ===》
         * 集合可以被划分为线程安全和非线程安全的。
         * （1）Vector 是用同步方法来实现线程安全的,
         * （2）而和它相似的ArrayList不是线程安全的。
         *
         */
    }
}
